﻿local addon, ns = ...
local cfg = ns.cfg
local LabelUI = ns.LabelUI
local timers = {}
local _G = _G

local toc = LabelUI.toc
local Kill = LabelUI.Kill
local classcolor
local point = LabelUI.point

local texture = {}

local LoadConfig = function()
	classcolor = cfg.classcolor
	texture.statusbar = cfg.statusbar
	texture.buffborder = cfg.buffborder
	texture.textureBackground =cfg.textureBackground3
	texture.textureBar = cfg.textureBar	
end

-- temp ench frame

local textureMapping = {
    [1] = 16,   --Main hand
    [2] = 17,   --Off-hand
    [3] = 18,   --Ranged
};
 
local function TemporaryEnchantFrameUpdate()
	local textureMapping = {
    	[16] = 1,   --Main hand
    	[17] = 3,   --Off-hand
 	}
	for i=1, NUM_TEMP_ENCHANT_FRAMES do
        local enchantButton = _G["TempEnchant"..i]
		enchantButton:SetWidth(cfg.frames.player.enchant.size)
		enchantButton:SetHeight(cfg.frames.player.enchant.size)
		_G[enchantButton:GetName().."Icon"]:Hide()
		_G[enchantButton:GetName().."Border"]:Hide()
	if not  enchantButton.cd then
		enchantButton.cd = CreateFrame("Cooldown", nil, enchantButton)
		if cfg.frames.player.enchant.rewerscd then
			enchantButton.cd:SetAllPoints(enchantButton)
			enchantButton.cd:SetReverse(true)
		else
  			enchantButton.cd:SetPoint('TOPLEFT',enchantButton,'TOPLEFT', cfg.frames.player.enchant.border, -cfg.frames.player.enchant.border)
 			enchantButton.cd:SetPoint('BOTTOMRIGHT',enchantButton,'BOTTOMRIGHT', -cfg.frames.player.enchant.border, cfg.frames.player.enchant.border)			
		end
	end
	if not enchantButton.icon then 
		enchantButton.icon = enchantButton:CreateTexture(nil, "BORDER")
		enchantButton.icon:SetTexCoord(0.07,0.93,0.07,0.93)
  		enchantButton.icon:SetPoint('TOPLEFT',enchantButton,'TOPLEFT', cfg.frames.player.enchant.border, -cfg.frames.player.enchant.border)
		enchantButton.icon:SetPoint('BOTTOMRIGHT',enchantButton,'BOTTOMRIGHT', -cfg.frames.player.enchant.border, cfg.frames.player.enchant.border)
	end
	if not enchantButton.iconBG then
		enchantButton.iconBG = enchantButton:CreateTexture(nil, "BACKGROUND")
		enchantButton.iconBG:SetAllPoints(enchantButton)
		enchantButton.iconBG:SetTexture(0, 0, 0, 0.4)
	end
	hooksecurefunc(enchantButton, "Show", function(self)
	--enchantButton:HookScript("OnShow", function(self)
		local hasEnchant, enchantExpiration, enchantCharges = select(textureMapping[self:GetID()], GetWeaponEnchantInfo())
		self.icon:SetTexture(GetInventoryItemTexture("player", self:GetID()))
		if ( enchantExpiration ) then	
			if not self.cd.timeleft or self.cd.itemIndex ~= itemIndex or (enchantExpiration/1000 >= (self.cd.duration or 0))then
				self.cd.timeleft = GetTime()
				self.cd.duration = enchantExpiration/1000
				self.cd.itemIndex = itemIndex
				self.cd:SetCooldown(self.cd.timeleft, self.cd.duration)
			end					
	    	--self.cd:SetCooldown(GetTime(), enchantExpiration/1000)
	   		self.cd:Show() 
		end
	end)
	hooksecurefunc(enchantButton, "Hide", function(self)
    	self.cd:Hide()
		enchantButton.cd.timeleft = nil 
	end)
	end
end

local function TempEnchantButtonOnEnter(self)
    GameTooltip:SetOwner(self, "ANCHOR_BOTTOMRIGHT");
    GameTooltip:SetInventoryItem("player", self:GetID());
end

--Buff frame

local UpdateBufFramePoint = function()
	if cfg.frames.player.enchant then
		_G["TempEnchant1"]:ClearAllPoints()
		_G["TempEnchant2"]:ClearAllPoints()
		_G["TempEnchant1"]:SetPoint(cfg.frames.player.enchant.pos.a1, point(cfg.frames.player.enchant.pos.af ,oUF_Player), cfg.frames.player.enchant.pos.a2, cfg.frames.player.enchant.pos.x, cfg.frames.player.enchant.pos.y)
		if cfg.frames.player.enchant.grow == "RIGHT" then
			_G["TempEnchant2"]:SetPoint("LEFT", _G["TempEnchant1"], "RIGHT", cfg.frames.player.enchant.space, 0)
		elseif cfg.frames.player.enchant.grow == "LEFT" then
			_G["TempEnchant2"]:SetPoint("RIGHT", _G["TempEnchant1"], "LEFT", -cfg.frames.player.enchant.space, 0)
		elseif cfg.frames.player.enchant.grow == "DOWN" then
			_G["TempEnchant2"]:SetPoint("TOP", _G["TempEnchant1"], "BOTTOM", 0, -cfg.frames.player.enchant.space)
		elseif cfg.frames.player.enchant.grow == "UP" then
			_G["TempEnchant2"]:SetPoint("BOTTOM", _G["TempEnchant1"], "TOP", 0, cfg.frames.player.enchant.space)
		end
	else
		Kill(_G["TempEnchant1"])
		Kill(_G["TempEnchant2"])
	end
	BuffFrame:ClearAllPoints()
	BuffFrame:SetPoint(cfg.frames.player.bufs.pos.a1,point(cfg.frames.player.bufs.pos.af, oUF_Player),cfg.frames.player.bufs.pos.a2, cfg.frames.player.bufs.pos.x, cfg.frames.player.bufs.pos.y)
	local maxdebuff = DEBUFF_MAX_DISPLAY
	DEBUFF_MAX_DISPLAY = 0
	-- Hide debuf if it exists during reload ui.
	for i = 1, maxdebuff do
		local debuff = _G["DebuffButton"..i]
		if debuff then
        	Kill(debuff)
		end
	end
	BUFF_ROW_SPACING = cfg.frames.player.bufs.space - 2
	BUFFS_PER_ROW = floor(cfg.frames.player.bufs.width / cfg.frames.player.bufs.size)
	BUFF_BUTTON_HEIGHT = cfg.frames.player.bufs.size
end

local UpdateBufsPosition = function(buff, first, prevbuff)
	if first then
		buff:SetPoint(cfg.frames.player.bufs.anchor, BuffFrame, cfg.frames.player.bufs.anchor, 0, 0)
	else
		if cfg.frames.player.bufs.grow.x == 'LEFT' then
			buff:SetPoint("RIGHT", prevbuff, "LEFT", -cfg.frames.player.bufs.space, 0)
		else
			buff:SetPoint("LEFT", prevbuff, "RIGHT", cfg.frames.player.bufs.space, 0)			
		end
	end		
	
end

local UpdateTooltip = function(self, Index, Flag, unit)
	GameTooltip:SetUnitAura(unit, Index, Flag)
end

local OnEnter = function(self, Index, Flag, unit)
	local name = UnitAura(unit, Index, Flag)
	if(not name) then return end

	GameTooltip:SetOwner(self, "ANCHOR_BOTTOMRIGHT")
	UpdateTooltip(self, Index, Flag, unit)
end

local OnLeave = function()
	GameTooltip:Hide()
end

local BuffFrameUpdateAllBuffAnchors = function()
    local buff, previousBuff, aboveBuff, index;
    local numBuffs = 0;
    local numAuraRows = 0;
    local slack = 0; --BuffFrame.numEnchants;
	if (toc < 50000) then
    if ( BuffFrame.numConsolidated > 0 ) then
        slack = slack + 1;  -- one icon for all consolidated buffs
    end
    end 
    for i = 1, BUFF_ACTUAL_DISPLAY do
        buff = _G["BuffButton"..i];
	buff:SetWidth(cfg.frames.player.bufs.size)
	buff:SetHeight(cfg.frames.player.bufs.size)
	local name, rank, texture, count, debuffType, duration, expirationTime, _, _, shouldConsolidate = UnitAura("player", i);
	local icon = _G["BuffButton"..i.."Icon"];
	icon:Hide()
	if not buff.cd then
		buff.cd = CreateFrame("Cooldown", nil, buff)
		if cfg.frames.player.bufs.rewerscd then
			buff.cd:SetAllPoints(buff)
			buff.cd:SetReverse(true)
		else
  			buff.cd:SetPoint('TOPLEFT',buff,'TOPLEFT', cfg.frames.player.bufs.border, -cfg.frames.player.bufs.border)
 			buff.cd:SetPoint('BOTTOMRIGHT',buff,'BOTTOMRIGHT', -cfg.frames.player.bufs.border, cfg.frames.player.bufs.border)			
		end
	end
        if ( duration and duration > 0 and expirationTime ) and buff.cd then
	    buff.cd:SetCooldown(expirationTime - duration, duration)
	    buff.cd:Show() 
        else
	    buff.cd:Hide() 
        end
	if not buff.icon then 
		buff.icon = buff:CreateTexture(nil, "BORDER")
		buff.icon:SetTexCoord(0.07,0.93,0.07,0.93)
  		buff.icon:SetPoint('TOPLEFT',buff,'TOPLEFT', cfg.frames.player.bufs.border, -cfg.frames.player.bufs.border)
 		buff.icon:SetPoint('BOTTOMRIGHT',buff,'BOTTOMRIGHT', -cfg.frames.player.bufs.border, cfg.frames.player.bufs.border)
	end
	if not buff.iconBG then
		buff.iconBG = buff:CreateTexture(nil, "BACKGROUND")
		buff.iconBG:SetAllPoints(buff)
		buff.iconBG:SetTexture(0, 0, 0, 0.4)
	end

	if not buff.counts then
		buff.counts = buff:CreateFontString(nil, "OVERLAY")
		buff.counts:SetFontObject(NumberFontNormal)
		buff.counts:SetPoint("BOTTOMRIGHT", buff, "BOTTOMRIGHT", -1, 0)
	end

	buff.count:Hide()

 	buff.icon:SetTexture(texture);
        if ( count and count > 1 ) then
            buff.counts:SetText(count);
            buff.counts:Show();
        else
            buff.counts:Hide();
        end

	if not buff.ScriptHooked then
  		buff:HookScript("OnEnter", function(self)
			OnEnter(self, i, 'HELPFUL', "player")
		end)
		buff.ScriptHooked = true
	end
	

	
        if ( buff.consolidated ) then  
            if ( buff.parent == BuffFrame ) then
                buff:SetParent(ConsolidatedBuffsContainer);
                buff.parent = ConsolidatedBuffsContainer;
            end
        else
            numBuffs = numBuffs + 1;
            index = numBuffs + slack;
            if ( buff.parent ~= BuffFrame ) then
                buff.count:SetFontObject(NumberFontNormal);
                buff:SetParent(BuffFrame);
                buff.parent = BuffFrame;
            end
            buff:ClearAllPoints();
            if ( (index > 1) and (mod(index, BUFFS_PER_ROW) == 1) ) then
                -- New row
                numAuraRows = numAuraRows + 1;
                if ( index == BUFFS_PER_ROW+1 ) then
		    if cfg.frames.player.bufs.grow.y == 'UP' then
			buff:SetPoint("BOTTOM", aboveBuff, "TOP", 0, cfg.frames.player.bufs.space)
		    else
			buff:SetPoint("TOP", aboveBuff, "BOTTOM", 0, -cfg.frames.player.bufs.space)			
		    end
                else
		    if cfg.frames.player.bufs.grow.y == 'UP' then
			buff:SetPoint("BOTTOM", aboveBuff, "TOP", 0, cfg.frames.player.bufs.space)
		    else
			buff:SetPoint("TOP", aboveBuff, "BOTTOM", 0, -cfg.frames.player.bufs.space)			
		    end
                end
                aboveBuff = buff;
            elseif ( index == 1 ) then
                numAuraRows = 1;
		UpdateBufsPosition(buff, true);
		aboveBuff = buff
            else
                if ( numBuffs == 1 ) then
		    UpdateBufsPosition(buff, true);
		    aboveBuff = buff
                else
		    UpdateBufsPosition(buff, false, previousBuff);
                end
            end
            previousBuff = buff;
        end
    end
end

function AuraButtonUpdate(buttonName, index, filter)
	local buffName = buttonName..index;
    local buff = _G[buffName];
	if ( GameTooltip:IsOwned(buff) ) then
		GameTooltip:SetOwner(buff, "ANCHOR_BOTTOMRIGHT")
        GameTooltip:SetUnitAura("player", index, 'HELPFUL')
    end	
end

local UpdateBlizzardBufFrame = function()

    ConsolidatedBuffs:Hide()

    UpdateBufFramePoint()

    hooksecurefunc("BuffFrame_UpdateAllBuffAnchors",         BuffFrameUpdateAllBuffAnchors)
    if cfg.frames.player.enchant then
    	--hooksecurefunc("TemporaryEnchantFrame_Update",         TemporaryEnchantFrameUpdate)
		TemporaryEnchantFrameUpdate()
    	hooksecurefunc("TempEnchantButton_OnEnter",         TempEnchantButtonOnEnter)
    end

	BuffFrame_UpdateAllBuffAnchors()
	TemporaryEnchantFrame_Update()

end

local PostCreateIconDebuffs = function(this, aura)
  local type = this.thistype
  local unit = this.unit 
  if unit == "tracking" then
  	if type == "debufs" then
		aura.unit = "target"
  	elseif type == "bufs" then
        	aura.unit = "player"
  	end	
  else
  	aura.unit = unit
  end
  if type == "debufs" then
	aura.bufftype = 'HARMFUL'
  elseif type == "bufs" then
        aura.bufftype = 'HELPFUL'
  end
  if cfg.frames[unit][type].countsize then
  	aura.count:SetFont(cfg.font, cfg.frames[unit][type].fontsize, "OUTLINE")
  end
  aura.icon:SetTexCoord(0.07,0.93,0.07,0.93)
  aura.icon:SetPoint('TOPLEFT',aura,'TOPLEFT', cfg.frames[unit][type].border, -cfg.frames[unit][type].border)
  aura.icon:SetPoint('BOTTOMRIGHT',aura,'BOTTOMRIGHT', -cfg.frames[unit][type].border, cfg.frames[unit][type].border)
  if not aura.iconBG then
  	aura.iconBG = aura:CreateTexture(nil, "BACKGROUND")
  end
  aura.iconBG:SetAllPoints(aura)
  aura.iconBG:SetTexture(0, 0, 0, 0.4)
  if cfg.frames[unit][type].statusbar ~= 0 then
    if not aura.status then
	aura.status = CreateFrame('Frame', nil, aura) 
    end
    aura.status:SetPoint('TOPLEFT',aura,'TOPRIGHT', 0, 0)
    aura.status:SetWidth(cfg.frames[unit][type].statusbar - cfg.frames[unit][type].size)
    aura.status:SetHeight(cfg.frames[unit][type].size)
    if not aura.statusbar then
       aura.statusbar = CreateFrame('StatusBar', nil, aura) 
    end
    aura.statusbar:SetPoint('TOPLEFT',aura.status,'TOPLEFT', 0, -cfg.frames[unit][type].border)
    aura.statusbar:SetPoint('BOTTOMRIGHT',aura.status,'BOTTOMRIGHT', -cfg.frames[unit][type].border, cfg.frames[unit][type].border)
    --aura.statusbar:SetBackdrop(texture.textureBar)
    --aura.statusbar:SetBackdropColor(0.18,0.18,0.18, 0.8)
    aura.statusbar:SetStatusBarTexture(texture.statusbar) 
    aura.statusbar:SetStatusBarColor(classcolor.r, classcolor.g, classcolor.b)
    if not aura.statusbarBG then
		aura.statusbarBG = aura.status:CreateTexture(nil, "BACKGROUND")
    end
    aura.statusbarBG:SetAllPoints(aura.status)
    aura.statusbarBG:SetTexture(0, 0, 0, 0.4)
    if not aura.statusbarText then
		aura.statusbarText = aura.status:CreateFontString(nil, "OVERLAY")
    end
    aura.statusbarText:SetFont(cfg.font, cfg.frames[unit][type].fontsize)
    aura.statusbarText:SetShadowOffset(1, -1) 
    aura.statusbarText:SetJustifyH('RIGHT')
    aura.statusbarText:SetPoint('RIGHT',aura.status,'RIGHT', -2, 0)
    if cfg.frames[unit][type].spells then
	if not aura.statusbarText2 then
	    aura.statusbarText2 = aura.status:CreateFontString(nil, "OVERLAY")
	end
	aura.statusbarText2:SetFont(cfg.font, cfg.frames[unit][type].fontsize)
	aura.statusbarText2:SetShadowOffset(1, -1) 
	aura.statusbarText2:SetJustifyH('LEFT')
	aura.statusbarText2:SetWidth((cfg.frames[unit][type].statusbar - cfg.frames[unit][type].size) * 0.75)
	aura.statusbarText2:SetHeight(cfg.frames[unit][type].size)
	aura.statusbarText2:SetPoint('LEFT',aura.status,'LEFT', 2, 0)
    end
  else
    aura.cd:SetPoint('TOPLEFT',aura,'TOPLEFT', cfg.frames[unit][type].border, -cfg.frames[unit][type].border)
    aura.cd:SetPoint('BOTTOMRIGHT',aura,'BOTTOMRIGHT', -cfg.frames[unit][type].border, cfg.frames[unit][type].border)
  end
  aura:SetFrameStrata("BACKGROUND")
end

local UpdateTimers = function(unit)
	for k,v in pairs(timers) do
		local name, rank, texture, count, dtype, duration, timeLeft = UnitAura(v.unit, v:GetID(), v.bufftype)
		if name then
		timeLeft = timeLeft - GetTime()
		if duration ~= v.duration then
			v.statusbar:SetMinMaxValues(0, duration)
			v.duration = duration
		end
		if timeLeft < 0.05 then
			timers[k] = nil
		else
			if timeLeft < v.lasttime - 0.1 then
				v.statusbar:SetValue(timeLeft)
				if timeLeft > 60 then
					local sektime = math.floor(mod(timeLeft, 60))
					v.statusbarText:SetText(tostring(math.floor((timeLeft)/60))..":"..tostring(math.floor(sektime/10))..tostring(math.floor(mod(sektime, 10))))
				else
					v.statusbarText:SetText(tostring(math.floor(timeLeft)).."."..tostring(math.floor(mod(timeLeft*10, 10))))
				end
				v.lasttime = timeLeft
			end
		end
		else
			timers[k] = nil
		end
	end
end
local UpdateBuffs = CreateFrame("Frame")
UpdateBuffs:SetScript("OnUpdate", UpdateTimers)

local PostUpdateIconDebuffs = function(this, unit, icon, index, offset)
	local name, rank, texture, count, dtype, duration, timeLeft = UnitAura(unit, index, icon.bufftype)
	if icon.statusbarText2 then 
		icon.statusbarText2:SetText(name) 
	end
	timeLeft = timeLeft - GetTime()
	if timeLeft < 0.05 then
		icon.statusbar:SetMinMaxValues(0, 1)
		icon.statusbar:SetValue(1)
		icon.statusbarText:SetText()
	else
		icon.statusbar:SetMinMaxValues(0, duration)
		icon.statusbar:SetValue(timeLeft)
		icon.duration = duration
		icon.lasttime = timeLeft
		if timeLeft > 60 then
			local sektime = math.floor(mod(timeLeft, 60))
			icon.statusbarText:SetText(tostring(math.floor((timeLeft)/60))..":"..tostring(math.floor(sektime/10))..tostring(math.floor(mod(sektime, 10))))
		else
			icon.statusbarText:SetText(tostring(math.floor(timeLeft)).."."..tostring(math.floor(mod(timeLeft*10, 10))))
		end
		table.insert(timers, icon)
	end
	--icon.unit = unit
	--icon:SetScript("OnUpdate", function()
	--	UpdateTimers()
	--end)
  	icon.statusbar:SetScript("OnEnter", function()
		OnEnter(icon, index, icon.bufftype, unit)
	end)
  	icon.statusbar:SetScript("OnLeave", OnLeave) 
end

local SpawnAura = function(self, unit, type)
	local auras
	auras = CreateFrame('Frame', nil, self)
	auras.thistype = type
	auras.unit = unit
	auras.size = cfg.frames[unit][type].size
	auras.spacing = cfg.frames[unit][type].space
	auras:SetWidth(cfg.frames[unit][type].width)
	auras:SetHeight(cfg.frames[unit][type].height)
	auras.initialAnchor = cfg.frames[unit][type].anchor
	auras.showDebuffType = cfg.frames[unit][type].showtypes
	auras.showBuffType = cfg.frames[unit][type].showtypes
	if type == "aura" then
		auras.numBuffs = cfg.frames[unit][type].num.b
		auras.numDebuffs = cfg.frames[unit][type].num.d
	else
		auras.num = cfg.frames[unit][type].num
	end
	if cfg.frames[unit][type].spells or cfg.frames[unit][type].tracking then
		local spells
		local tracking
		if unit == "tracking" then
			tracking = cfg.frames[unit][type].spells
		else
			spells = cfg.frames[unit][type].spells
			tracking = cfg.frames.tracking[type].spells
		end
		auras.CustomFilter = function(icons, unit, icon, name, rank, texture, count, dtype, duration, timeLeft, caster)
			if spells and tContains(spells, name) or tracking and tContains(tracking, name) and (caster == "player") then
				return true
			end
		end 
	end
	auras.filter = false
	auras.disableCooldown = (cfg.frames[unit][type].statusbar ~= 0)
	auras:SetPoint(cfg.frames[unit][type].pos.a1,point(cfg.frames[unit][type].pos.af, self),cfg.frames[unit][type].pos.a2, cfg.frames[unit][type].pos.x, cfg.frames[unit][type].pos.y)
	auras['growth-x'] = cfg.frames[unit][type].grow.x
	auras['growth-y'] = cfg.frames[unit][type].grow.y
	auras.PostCreateIcon = PostCreateIconDebuffs
	if cfg.frames[unit][type].statusbar ~= 0 then
		auras.PostUpdateIcon = PostUpdateIconDebuffs
	end
	auras.showType = cfg.frames[unit][type].showtypes
	return auras 
end
LabelUI.SpawnAura = SpawnAura
LabelUI.UpdateBlizzardBufFrame = UpdateBlizzardBufFrame

local function Init()
	LoadConfig()
end
LabelUI:AddInit(Init, "BuffFrames")